﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
/************************************************
*********** LDAP Mandatory Libraries ************
************************************************/
using System.Configuration;
using System.DirectoryServices;
using System.DirectoryServices.AccountManagement;
using System.DirectoryServices.Protocols;
using System.Text.RegularExpressions;

namespace LDAP_Manager
{
    public class ADUser
    {
        #region Fields
        private string firstName;
        private string middleName;
        private string lastName;
        private string loginName;
        private string loginNameWithDomain;
        private string streetAddress;
        private string city;
        private string state;
        private string postalCode;
        private string country;
        private string homePhone;
        private string extension;
        private string mobile;
        private string fax;
        private string emailAddress;
        private string title;
        private string company;
        private string manager;
        private string managerName;
        private string department;
        private List<string> memberOf;
        #endregion

        #region Properties
        /// <summary>
        /// LDAP User First Name
        /// </summary>
        public string FirstName
        {
            get { return firstName; }
            set { firstName = value; }
        }
        /// <summary>
        /// LDAP User Middle Name
        /// </summary>
        public string MiddleName
        {
            get { return middleName; }
            set { middleName = value; }
        }
        /// <summary>
        /// LDAP User Last Name
        /// </summary>
        public string LastName
        {
            get { return lastName; }
            set { lastName = value; }
        }
        /// <summary>
        /// LDAP User Login Name
        /// </summary>
        public string LoginName
        {
            get { return loginName; }
            set { loginName = value; }
        }
        /// <summary>
        /// LDAP User Login Name (Including Domain)
        /// </summary>
        public string LoginNameWithDomain
        {
            get { return loginNameWithDomain; }
            set { loginNameWithDomain = value; }
        }
        /// <summary>
        /// LDAP User Address
        /// </summary>
        public string StreetAddress
        {
            get { return streetAddress; }
            set { streetAddress = value; }
        }
        /// <summary>
        /// LDAP User City
        /// </summary>
        public string City
        {
            get { return city; }
            set { city = value; }
        }
        /// <summary>
        /// LDAP User State
        /// </summary>
        public string State
        {
            get { return state; }
            set { state = value; }
        }
        /// <summary>
        /// LDAP User Postal Code
        /// </summary>
        public string PostalCode
        {
            get { return postalCode; }
            set { postalCode = value; }
        }
        /// <summary>
        /// LDAP User Country
        /// </summary>
        public string Country
        {
            get { return country; }
            set { country = value; }
        }
        /// <summary>
        /// LDAP User Home Phone
        /// </summary>
        public string HomePhone
        {
            get { return homePhone; }
            set { homePhone = value; }
        }
        /// <summary>
        /// LDAP User Extension
        /// </summary>
        public string Extension
        {
            get { return extension; }
            set { extension = value; }
        }
        /// <summary>
        /// LDAP User Mobile Number
        /// </summary>
        public string Mobile
        {
            get { return mobile; }
            set { mobile = value; }
        }
        /// <summary>
        /// LDAP User Fax Number
        /// </summary>
        public string Fax
        {
            get { return fax; }
            set { fax = value; }
        }
        /// <summary>
        /// LDAP User Email Address
        /// </summary>
        public string EmailAddress
        {
            get { return emailAddress; }
            set { emailAddress = value; }
        }
        /// <summary>
        /// LDAP User Position Title
        /// </summary>
        public string Title
        {
            get { return title; }
            set { title = value; }
        }
        /// <summary>
        /// LDAP User Company
        /// </summary>
        public string Company
        {
            get { return company; }
            set { company = value; }
        }
        /// <summary>
        /// LDAP User's Manager
        /// </summary>
        public ADUser Manager
        {
            get
            {
                if (!String.IsNullOrEmpty(managerName))
                {
                    LDAPManager ad = new LDAPManager();
                    return ad.GetUserByFullName(managerName);
                }
                return null;
            }
        }
        /// <summary>
        /// LDAP User's Manager Name
        /// </summary>
        public string ManagerName
        {
            get { return managerName; }
            set { managerName = value; }
        }
        /// <summary>
        /// LDAP User's Department
        /// </summary>
        public string Department
        {
            get { return department; }
            set { department = value; }
        }
        /// <summary>
        /// LDAP User's Membership
        /// </summary>
        public List<string> MemberOf
        {
            get { return memberOf; }
            set { memberOf = value; }
        }
        #endregion

        #region Constructor
        /// <summary>
        /// Empty ADUser Constructor
        /// </summary>
        public ADUser() { }
        /// <summary>
        /// ADUser Constructor using all parameters
        /// </summary>
        /// <param name="pFirstName">LDAP User First Name</param>
        /// <param name="pMiddleName">LDAP User Middle Name</param>
        /// <param name="pLastName">LDAP User Last Name</param>
        /// <param name="pLoginName">LDAP User Login Name</param>
        /// <param name="pLoginNameWithDomain">LDAP User Login Name (Domain Name Included)</param>
        /// <param name="pStreetAddress">LDAp User Street Address</param>
        /// <param name="pCity">LDAP User City</param>
        /// <param name="pState">LDAP User State</param>
        /// <param name="pPostalCode">LDAp User Postal Code</param>
        /// <param name="pCountry">LDAP User Control</param>
        /// <param name="pHomePhone">LDAP User Home Phone</param>
        /// <param name="pExtension">LDAP User Extension</param>
        /// <param name="pMobile">LDAP User Mobile Number</param>
        /// <param name="pFax">LDAP User Fax Number</param>
        /// <param name="pEmailAddress">LDAP User Email Address</param>
        /// <param name="pTitle">LDAP User Position Title</param>
        /// <param name="pCompany">LDAP User's Company</param>
        /// <param name="pManager">LDAP User's Manager</param>
        /// <param name="pManagerName">LDAP User's Manager Name</param>
        /// <param name="pDepartment">LDAP User's Department</param>
        public ADUser(string pFirstName, string pMiddleName, string pLastName, string pLoginName,
            string pLoginNameWithDomain, string pStreetAddress, string pCity, string pState, string pPostalCode,
            string pCountry, string pHomePhone, string pExtension, string pMobile, string pFax, string pEmailAddress,
            string pTitle, string pCompany, string pManager, string pManagerName, string pDepartment)
        {
            this.firstName = pFirstName;
            this.middleName = pMiddleName;
            this.lastName = pLastName;
            this.loginName = pLoginName;
            this.loginNameWithDomain = pLoginNameWithDomain;
            this.streetAddress = pStreetAddress;
            this.city = pCity;
            this.state = pState;
            this.postalCode = pPostalCode;
            this.country = pCountry;
            this.homePhone = pHomePhone;
            this.extension = pExtension;
            this.mobile = pMobile;
            this.fax = pFax;
            this.emailAddress = pEmailAddress;
            this.title = pTitle;
            this.company = pCompany;
            this.manager = pManager;
            this.department = pDepartment;

        }
        /// <summary>
        /// ADUSer Constructor Getting info from LDAP
        /// </summary>
        /// <param name="pDirectoryUser">Directory Entry object with User Information</param>
        private ADUser(DirectoryEntry pDirectoryUser)
        {
            string filter = string.Format("(&(ObjectClass={0})(sAMAccountName={1}))", "person", pDirectoryUser.Username);

            DirectorySearcher searcher = new DirectorySearcher(pDirectoryUser);
            searcher.SearchScope = System.DirectoryServices.SearchScope.Subtree;
            searcher.ReferralChasing = ReferralChasingOption.All;
            searcher.Filter = filter;

            SearchResult result = searcher.FindOne();
            DirectoryEntry directoryEntry = result.GetDirectoryEntry();

            string domainAddress;
            string domainName;
            string userPrincipalName;

            firstName = GetProperty(directoryEntry, ADProperties.FIRSTNAME);
            middleName = GetProperty(directoryEntry, ADProperties.MIDDLENAME);
            lastName = GetProperty(directoryEntry, ADProperties.LASTNAME);
            loginName = GetProperty(directoryEntry, ADProperties.LOGINNAME);
            userPrincipalName = GetProperty(directoryEntry, ADProperties.USERPRINCIPALNAME);
            memberOf = new List<string>();
            foreach (object Membership in GetProperties(directoryEntry, ADProperties.MEMBEROF))
            {
                Regex R1 = new Regex(@"CN=([áéíóúA-Za-z0-9\-]+),OU");
                Match match = R1.Match(Membership.ToString());
                if (match.Success)
                {
                    string Group = match.Groups[1].Value;
                    memberOf.Add(Group);
                }
            }

            if (!String.IsNullOrEmpty(userPrincipalName))
            {
                domainAddress = userPrincipalName.Split('@')[1];
                domainName = domainAddress.Split('.').First();
            }
            else
            {
                domainAddress = String.Empty;
                domainName = String.Empty;
            }

            loginNameWithDomain = string.Format(@"{0}\{1}", domainName, loginName);
            streetAddress = GetProperty(directoryEntry, ADProperties.STREETADDRESS);
            city = GetProperty(directoryEntry, ADProperties.CITY);
            state = GetProperty(directoryEntry, ADProperties.STATE);
            postalCode = GetProperty(directoryEntry, ADProperties.POSTALCODE);
            country = GetProperty(directoryEntry, ADProperties.COUNTRY);
            company = GetProperty(directoryEntry, ADProperties.COMPANY);
            department = GetProperty(directoryEntry, ADProperties.DEPARTMENT);
            homePhone = GetProperty(directoryEntry, ADProperties.HOMEPHONE);
            extension = GetProperty(directoryEntry, ADProperties.EXTENSION);
            mobile = GetProperty(directoryEntry, ADProperties.MOBILE);
            fax = GetProperty(directoryEntry, ADProperties.FAX);
            emailAddress = GetProperty(directoryEntry, ADProperties.EMAILADDRESS);
            title = GetProperty(directoryEntry, ADProperties.TITLE);
            manager = GetProperty(directoryEntry, ADProperties.MANAGER);

            if (!String.IsNullOrEmpty(manager))
            {
                String[] managerArray = manager.Split(',');
                managerName = managerArray[0].Replace("CN=", "");
            }
        }
        #endregion

        #region Methods
        /// <summary>
        /// Getting User Directory Entry Property
        /// </summary>
        /// <param name="pUserDetail">Directory Entry User Detail</param>
        /// <param name="pPropertyName">Property Name to Obtain</param>
        /// <returns>Returns a String</returns>
        private static string GetProperty(DirectoryEntry pUserDetail, string pPropertyName)
        {
            if (pUserDetail.Properties.Contains(pPropertyName))
                return pUserDetail.Properties[pPropertyName][0].ToString();
            else
                return string.Empty;
        }

        private static PropertyValueCollection GetProperties(DirectoryEntry pUserDetail, string pPropertyName)
        {
            if (pUserDetail.Properties.Contains(pPropertyName))
                return pUserDetail.Properties[pPropertyName];
            else
                return null;
        }

        /// <summary>
        /// This function calls the class constructor and fills the object with the LDAP user information
        /// </summary>
        /// <param name="pDirectoryUser">Directory Entry User Information</param>
        /// <returns>Returns an ADUser Object</returns>
        public static ADUser GetUser(DirectoryEntry pDirectoryUser)
        {
            return new ADUser(pDirectoryUser);
        }
        #endregion
    }
}
